<template>
	<div :class="ns.b('container')">
		<el-upload :style="{
			'--upload-width': configure?.width || '148px',
			'--upload-height': configure?.height || '148px',
		}" list-type="picture-card" multiple :auto-upload="false" :file-list="fileList" :limit="props.configure?.limit"
			:disabled="props.configure?.disabled" :class="showAdd" :on-preview="handlePictureCardPreview"
			:on-remove="handleRemove" @change="handleChange">
			<el-icon>
				<Plus />
			</el-icon>
		</el-upload>

		<div :class="ns.be('container', 'desc')">
			{{ configure?.desc || '请上传jpg、jpeg、png,图片大小请小于2MB' }}
		</div>
	</div>

	<el-dialog append-to-body v-model="dialogVisible">
		<img :class="[ns.b('img')]" :src="dialogImageUrl" alt="Preview Image" />
	</el-dialog>
</template>

<script lang="ts" setup>
import { ref, PropType, watch, computed } from "vue";
import { Plus } from "@element-plus/icons-vue";
import { UploadProps, UploadUserFile, UploadFile, UploadFiles } from "element-plus";
import { useNamespace } from "@/hooks";
import { PyUploadImgType } from "./type";
import { HeadersType, HttpRequest, toFormData } from "@/http";
import { message } from "@pkg";
const ns = useNamespace("upload");
const props = defineProps<{
	modelValue: Array<string> | string,
	configure: PyUploadImgType
}>();
const uploadImg = async (url: string, file: any, fileType?: string) => {
	const res = await new HttpRequest(url, {
		header: HeadersType.FormData,
	}).post(toFormData({ file, fileType: fileType }));
	if (res?.success) {
		return res.data;
	} else {
		message.open({
			type: "error",
			title: "提示",
			message: "上传图片失败",
		});
		return;
	}
};
const emits = defineEmits(["update:modelValue", "onChange", "onRemove"]);
const fileList = ref<(UploadUserFile & { id?: string })[]>([]);

const showAdd = computed(() => {
	return fileList?.value.length >= (props.configure?.limit || 5) ? ns.b("main") : "";
});

//change事件
const handleChange = async (uploadFile: UploadFile, uploadFiles: UploadFiles) => {
	const imageType = uploadFile.raw && uploadFile.raw.type;
	//设置图片限制
	if (
		imageType !== "image/jpeg" &&
		imageType !== "image/jpg" &&
		imageType !== "image/png"
	) {
		uploadFiles.pop();
		message.open({
			type: "error",
			title: "提示",
			message: "图片请上传jpg、jpeg、png格式!",
		});
		return false;
	} else if (uploadFile.raw && uploadFile.raw.size / 1024 / 1024 > 2) {
		uploadFiles.pop();
		message.open({
			type: "error",
			title: "提示",
			message: "图片大小不能超过2MB!",
		});
		return false;
	}

	let img;
	if (props.configure?.isAutoUpload) {
		img = await uploadImg(props.configure.url || "", uploadFile.raw);
		const index = uploadFiles.findIndex(e => e.uid == uploadFile.uid);
		if (index != -1 && img) {
			uploadFiles[index].url = img;
		}
		fileList.value = uploadFiles;
		emits("update:modelValue", fileList.value.map(e => e.url).join(","), img);
		emits("onChange", fileList.value.map(e => e.url).join(","), img);
		props.configure.changeAutoUpload &&
			props.configure.changeAutoUpload(fileList.value.map(e => e.url).join(","), img);
	} else {
		fileList.value = uploadFiles;
		emits("update:modelValue", fileList.value, uploadFile);
		emits("onChange", fileList.value, uploadFile);
		props.configure.change && props.configure.change(fileList.value, uploadFile);
	}

	return true;
};

//点击放大图片事件
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
const handlePictureCardPreview: UploadProps["onPreview"] = uploadFile => {
	dialogImageUrl.value = uploadFile.url!;
	dialogVisible.value = true;
};
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
	if (props.configure.isAutoUpload) {
		const index = fileList.value.findIndex(
			e => e.uid == (uploadFile as UploadFile & { id: string }).uid
		);
		if (index != -1) {
			fileList.value.splice(index, 1);
		}
		props.configure.removeAutoUpload &&
			props.configure.removeAutoUpload(
				fileList.value.map(e => e.url).join(","),
				uploadFile.url || ""
			);
		emits("update:modelValue", fileList.value.map(e => e.url).join(","), uploadFile.url);
		emits("onChange", fileList.value.map(e => e.url).join(","), uploadFile.url);
	} else {
		fileList.value = uploadFiles;
		props.configure.remove && props.configure.remove(fileList.value, uploadFile);
		emits("update:modelValue", fileList.value, uploadFile);
		emits("onChange", fileList.value, uploadFile);
	}
};

//获取当前值
const getData = () => {
	return fileList.value;
};

//设置当前值
const setData = (value: UploadUserFile[]) => {
	fileList.value = value;
};

watch(
	() => props.modelValue,
	val => {
		if (!val) return fileList.value = [];
		if (val instanceof Array) {
			// @ts-ignore
			fileList.value = val.map(item => {
				if (typeof item === "string") return { uid: item, url: item, name: item };
				return item;
			});
		} else if (typeof val === "string") {
			const imgs = val.split(",");
			if (!imgs?.length) {
				fileList.value = [];
				return;
			}
			imgs.forEach((e, index) => {
				const curImgFile = fileList.value[index];
				if (!curImgFile) {
					fileList.value.push({ uid: index + Math.random(), url: e, name: e + index });
				} else {
					if (curImgFile.url != e) {
						curImgFile.url = e;
					}
				}
			});
		} else {
			throw new Error(`请传入数组类型数据PyUploadImg:${val}`);
		}
	},
	{ immediate: true, deep: true }
);

//暴露方法
defineExpose({ getData, setData });
</script>
<style scoped lang="scss">
@include block(upload-container) {
	display: flex;
	flex-direction: column;

	@include element(desc) {
		color: var(--intent-color-error5);
	}
}

@include block(upload-main) {
	:deep(.el-upload) {
		display: none;
	}
}

@include block(upload-img) {
	width: 100%;
}

:deep(.el-upload-list__item) {
	width: var(--upload-width);
	height: var(--upload-height);
}

:deep(.el-upload--picture-card) {
	width: var(--upload-width);
	height: var(--upload-height);
}
</style>
